#include "udp_client.hpp"
#include <cstring>
#include <pthread.h>

using namespace std;

// 后两个参数，是目标服务器的IP和端口号
static void usage(char proc[])
{
    std::cout << "Usage:\n\t" << proc << " serverip serverport\n"
              << std::endl;
}

void *Recv(void *args)
{
    int sock = *(static_cast<int *>(args));

    while (true)
    {
        // 2.收消息
        char buffer[2048];
        struct sockaddr_in temp; // 记录谁发的消息
        memset(&temp, 0, sizeof(temp));
        socklen_t len = sizeof(temp);
        int n = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&temp, &len);
        if (n > 0)
        {
            buffer[n] = '\0';
            cout << buffer << endl;
        }
    }
}

// 客户端不需要bind，因为OS会自行分配，防止与其他客户端冲突
// 在第一次sendto时bind端口号，IP等
int main(int argc, char *argv[])
{

    if (argc != 3)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }

    // 创建套接字
    int _sock = socket(AF_INET, SOCK_DGRAM, 0);

    // 提取目标服务器的IP地址和端口号
    string serverIp = argv[1];
    uint16_t serverPort = atoi(argv[2]);

    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;                          // 标识符
    server.sin_addr.s_addr = inet_addr(serverIp.c_str()); // IP
    server.sin_port = htons(serverPort);                  // 端口号

    // 将收消息和发消息分成两个线程
    pthread_t tid;
    pthread_create(&tid, nullptr, Recv, &_sock);

    while (true)
    {
        // 1. 发消息
        string message;
        cerr << "please enter your message# ";
        getline(cin, message);
        sendto(_sock, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server));
    }

    return 0;
}